package com.carleasoft.mps.adu.business.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carleasoft.mps.adu.business.login.bean.BowOutVo;
import com.carleasoft.mps.adu.business.login.service.LoginService;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserDept;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserEntity;
import com.carleasoft.mps.adu.business.user.bean.entity.AuthorityUserPositionEntity;
import com.carleasoft.mps.adu.business.user.bean.po.AuthorityUserPo;
import com.carleasoft.mps.adu.business.user.bean.vo.AuthorityUserDetailVo;
import com.carleasoft.mps.adu.business.user.dao.AuthorityUserDao;
import com.carleasoft.mps.adu.business.user.dao.AuthorityUserDeptDao;
import com.carleasoft.mps.adu.business.user.dao.AuthorityUserPositionDao;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserDeptService;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserPositionService;
import com.carleasoft.mps.adu.business.user.service.AuthorityUserService;
import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.user.Constants;
import com.carleasoft.mps.core.user.UserDeptVo;
import com.carleasoft.mps.core.user.UserPositionVo;
import com.carleasoft.mps.core.utils.Base64Util;
import com.carleasoft.mps.core.utils.ConvertUtils;
import com.carleasoft.mps.core.utils.IBeanUtil;
import com.carleasoft.mps.core.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.carleasoft.mps.adu.common.constants.BusinessErrorEnum.DUPLICATE_USER_ACCOUNT;

/**
 * <p>Description: user serviceImpl</p>
 *
 * @author ztm
 * @since 2020-04-29
 */
@Service
public class AuthorityUserServiceImpl extends ServiceImpl<AuthorityUserDao, AuthorityUserEntity> implements AuthorityUserService {

    @Autowired
    private AuthorityUserPositionService authorityUserPositionService;
    @Autowired
    private AuthorityUserDeptService authorityUserDeptService;
    @Autowired
    private LoginService loginService;

    @Autowired
    private AuthorityUserDeptDao authorityUserDeptDao;
    @Autowired
    private AuthorityUserPositionDao authorityUserPositionDao;


    /**
     * 添加用户
     *
     * @param authorityUserPo
     * @return void
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public AuthorityUserEntity addUser(AuthorityUserPo authorityUserPo) {

        /**********业务校验************/
        AuthorityUserEntity one = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserAccount, authorityUserPo.getUserAccount()));
        if (Objects.nonNull(one)) {
            throw new BusinessException(DUPLICATE_USER_ACCOUNT);
        }
        String userCode = IdWorker.getIdStr();
        authorityUserPo.setUserCode(userCode);
        AuthorityUserEntity userEntity = ConvertUtils.sourceToTarget(authorityUserPo, AuthorityUserEntity.class);
        userEntity.setUserCat(Constants.ORDINARY_USER);
        userEntity.setUserCode(userCode);
        userEntity.setUserStatus(Constants.ENABLE);
        String userNumber = authorityUserPo.getUserNumber();
        String password = userNumber.substring(userNumber.length() - 6);
        String md5 = MD5Util.MD5(password);
        String userPassword = Base64Util.encode(md5);
        userEntity.setUserNumber(userNumber);
        userEntity.setUserPassword(userPassword);
        userEntity.setUserAccount(userNumber);
        //添加职务和部门对应关系
        if (CollUtil.isNotEmpty(authorityUserPo.getUserDeptPos())) {
            authorityUserPo.getUserDeptPos().forEach(userDeptItem -> {
                AuthorityUserDept authorityUserDept = BeanUtil.copyProperties(userDeptItem, AuthorityUserDept.class);
                if (authorityUserDept.getSort() == null || authorityUserDept.getSort() > 0) {
                    AuthorityUserDept sortType = this.authorityUserDeptService.getOne(Wrappers.<AuthorityUserDept>lambdaQuery()
                            .eq(AuthorityUserDept::getDeptCode, userDeptItem.getDeptCode())
                            .orderByDesc(AuthorityUserDept::getSort).last("limit 1"));
                    authorityUserDept.setSort(Objects.isNull(sortType) ? 1 : sortType.getSort() + 1);
                }
                authorityUserDept.setUserCode(userEntity.getUserCode());
                this.authorityUserDeptService.save(authorityUserDept);
                if (Objects.nonNull(userDeptItem.getUserPositionList())) {
                    userDeptItem.getUserPositionList().forEach(userPosItem -> {
                        AuthorityUserPositionEntity authorityUserPositionEntity = BeanUtil.copyProperties(userPosItem, AuthorityUserPositionEntity.class);
                        authorityUserPositionEntity.setUserCode(userEntity.getUserCode());
                        this.authorityUserPositionService.save(authorityUserPositionEntity);
                    });
                }
            });
        }
        this.save(userEntity);
        return userEntity;
    }

    /**
     * 用户修改接口
     *
     * @param authorityUserPo
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public AuthorityUserEntity updateUser(AuthorityUserPo authorityUserPo) {
        IBeanUtil.paramVerify(authorityUserPo, "userCode");


        /**********业务校验************/
        AuthorityUserEntity one = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserCode, authorityUserPo.getUserCode()));
        if (Objects.nonNull(one) && !authorityUserPo.getUserCode().equals(one.getUserCode())) {
            throw new BusinessException(DUPLICATE_USER_ACCOUNT);
        }
        List<AuthorityUserEntity> authorityUserEntities = this.list(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserNumber, authorityUserPo.getUserNumber())
                .ne(AuthorityUserEntity::getUserAccount, one.getUserAccount()));
        if (CollUtil.isNotEmpty(authorityUserEntities)) {
            throw new BusinessException(DUPLICATE_USER_ACCOUNT);
        }
        if (CollUtil.isNotEmpty(authorityUserPo.getUserDeptVos()) && StrUtil.isNotBlank(authorityUserPo.getUserDeptVos().get(0).getDeptCode())){
            authorityUserPo.setUserDeptPos(authorityUserPo.getUserDeptVos());
        }
        AuthorityUserEntity userEntity = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserCode, authorityUserPo.getUserCode()));
        if (userEntity != null) {
            if (StrUtil.isNotBlank(authorityUserPo.getUserTypeCode())) {
                userEntity.setUserTypeCode(authorityUserPo.getUserTypeCode());
            }
            userEntity.setUserName(authorityUserPo.getUserName());
            userEntity.setUserAccount(authorityUserPo.getUserNumber());
            userEntity.setRemark(authorityUserPo.getRemark());
            // 原密码
            String currentPassword = userEntity.getUserPassword();

            // 初始密码
            String numberPassword = userEntity.getUserNumber().substring(userEntity.getUserNumber().length() - 6);
            String md5Password = MD5Util.MD5(numberPassword);
            String numberPass = Base64Util.encode(md5Password);
            if (currentPassword.equals(numberPass)) {
                String nowWord = authorityUserPo.getUserNumber().substring(userEntity.getUserNumber().length() - 6);
                String md5Word = MD5Util.MD5(nowWord);
                String currentWord = Base64Util.encode(md5Word);
                userEntity.setUserPassword(currentWord);
            } else {
                userEntity.setUserPassword(currentPassword);
            }
            if (StrUtil.isNotBlank(authorityUserPo.getUserNumber())) {
                userEntity.setUserNumber(authorityUserPo.getUserNumber());
            }
        }

        //添加职务和部门对应关系
        this.authorityUserDeptService.remove(Wrappers.<AuthorityUserDept>lambdaQuery().eq(AuthorityUserDept::getUserCode, authorityUserPo.getUserCode()));
        this.authorityUserPositionService.remove(Wrappers.<AuthorityUserPositionEntity>lambdaQuery().eq(AuthorityUserPositionEntity::getUserCode, authorityUserPo.getUserCode()));
        if (CollUtil.isNotEmpty(authorityUserPo.getUserDeptPos())) {
            authorityUserPo.getUserDeptPos().forEach(userDeptItem -> {
                AuthorityUserDept authorityUserDept = BeanUtil.copyProperties(userDeptItem, AuthorityUserDept.class);
                authorityUserDept.setUserCode(userEntity.getUserCode());
                if (authorityUserDept.getSort() == null || authorityUserDept.getSort() > 0) {
                    AuthorityUserDept sortType = this.authorityUserDeptService.getOne(Wrappers.<AuthorityUserDept>lambdaQuery()
                            .eq(AuthorityUserDept::getDeptCode, userDeptItem.getDeptCode())
                            .orderByDesc(AuthorityUserDept::getSort).last("limit 1"));
                    authorityUserDept.setSort(Objects.isNull(sortType) ? 1 : sortType.getSort() + 1);
                }
                this.authorityUserDeptService.save(authorityUserDept);
                if (Objects.nonNull(userDeptItem.getUserPositionList())) {
                    userDeptItem.getUserPositionList().forEach(userPosItem -> {
                        AuthorityUserPositionEntity authorityUserPositionEntity = BeanUtil.copyProperties(userPosItem, AuthorityUserPositionEntity.class);
                        authorityUserPositionEntity.setUserCode(userEntity.getUserCode());
                        this.authorityUserPositionService.save(authorityUserPositionEntity);
                    });
                }
            });
        }

        this.saveOrUpdate(userEntity);
        return userEntity;
    }


    /**
     * 删除用户
     *
     * @param authorityUserPo
     * @return void
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Boolean deleteUser(AuthorityUserPo authorityUserPo) {
        IBeanUtil.paramVerify(authorityUserPo, "userCode");
        boolean result;
        //删除用户关系
        String userCode = authorityUserPo.getUserCode();
        authorityUserPositionService.remove(Wrappers.<AuthorityUserPositionEntity>lambdaQuery().eq(AuthorityUserPositionEntity::getUserCode, userCode));
        authorityUserDeptService.remove(Wrappers.<AuthorityUserDept>lambdaQuery().eq(AuthorityUserDept::getUserCode, userCode));
        //删除用户
        result = this.remove(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserCode, userCode));

        //删除成功，把被删除用户token踢掉
        BowOutVo bowOutVo = new BowOutVo();
        bowOutVo.setUserCode(userCode);
        bowOutVo.setLoginType(Constants.WEB);
        loginService.bowOut(bowOutVo);
        return result;
    }


    /**
     * 用户详情查询
     *
     * @param authorityUserPo
     * @return userCode
     */
    @Override
    public AuthorityUserDetailVo getUserByCode(AuthorityUserPo authorityUserPo) {
        IBeanUtil.paramVerify(authorityUserPo, "userCode");
        AuthorityUserEntity authorityUserEntity = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserCode, authorityUserPo.getUserCode()));
        AuthorityUserDetailVo authorityUserVo = ConvertUtils.sourceToTarget(authorityUserEntity, AuthorityUserDetailVo.class);
        List<UserDeptVo> userDeptVos = this.authorityUserDeptDao.getDeptByUserCode(authorityUserEntity.getUserCode());
        List<AuthorityUserPositionEntity> userPositions = authorityUserPositionDao.selectPositionByUserCode(authorityUserPo.getUserCode());
        userDeptVos.forEach(userDeptItem -> {
                    userPositions.forEach(posItem -> {
                        if (userDeptItem.getDeptCode().equals(posItem.getDeptCode())) {
                            userDeptItem.getUserPositionList().add(ConvertUtils.sourceToTarget(posItem, UserPositionVo.class));
                        }
                    });
                }
        );

        authorityUserVo.setUserDeptVos(userDeptVos);
        return authorityUserVo;
    }


    /**
     * 密码修改
     *
     * @param authorityUserPo
     * @return void
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean changePassword(AuthorityUserPo authorityUserPo) {
        IBeanUtil.paramVerify(authorityUserPo, "userPassword");
        //修改密码
        return this.update(Wrappers.<AuthorityUserEntity>lambdaUpdate()
                .eq(AuthorityUserEntity::getUserCode, authorityUserPo.getUserCode())
                .set(AuthorityUserEntity::getUserPassword, authorityUserPo.getUserPassword()));

    }


    @Override
    public AuthorityUserDetailVo getByUserAccount(AuthorityUserPo authorityUserPo) {
        AuthorityUserEntity authorityUserEntity = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery().eq(AuthorityUserEntity::getUserAccount, authorityUserPo.getUserAccount()));
        if (Objects.nonNull(authorityUserEntity)) {
            authorityUserPo.setUserAccount(authorityUserEntity.getUserCode());
            return this.getUserByCode(authorityUserPo);
        } else {
            return null;
        }
    }


    @Override
    public void existUser(String userAccount, String userCode) {
        //校验用户账号的是否重复
        AuthorityUserEntity userEntity = this.getOne(Wrappers.<AuthorityUserEntity>lambdaQuery()
                .eq(AuthorityUserEntity::getUserAccount, userAccount)
                .ne(AuthorityUserEntity::getUserCode, userCode));
        if (Objects.nonNull(userEntity)) {
            throw new BusinessException(DUPLICATE_USER_ACCOUNT);
        }
    }


}
